123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813 |
- function varargout = View4D_BRIK(varargin)
- % Viewer for 4D .BRIK file.
- % - Allows for montages across both slice dimensions and time.
- % - Also displays timeseries for selected voxel.
- %
- % Usage:
- % View4D_BRIK(anat_img, brik_img, cellarray_of_other_funcdata, custom_legendnames)
- %
- % Required Inputs:
- % anat_img: Is your anatomical+tlrc.BRIK that serves as underlay.
- % brik_img: Is your the functional+tlrc.BRIK file that serves as overlay.
- %
- % Optional Inputs (Can leave empty if not desired):
- % cellarray_of_other_funcdata:
- % - In the viewer, timeseries data of the selected voxel for the primary functional image
- % is plotted in a solid line. If you wish to overlay timeseries data from other functional
- % data onto the plot, you can specify the other datasets in the third argument.
- % - If left empty, only the primary functional image will be plotted.
- %
- % custom_legendnames:
- % - Allows you to specify your own legend for the voxel timeseries plot.
- % - If left empty, dataset names will be used.
- %
- %
- % Examples:
- % View4D_BRIK('anat+tlrc.BRIK', 'functional+tlrc.BRIK', [], [])
- %
- % View4D_BRIK('anat+tlrc.BRIK', 'Cond1+tlrc.BRIK', ...
- % {'Cond2+tlrc.BRIK, ControlCond+tlrc.BRIK'}, {'Cond1', 'Cond2', Control'})
- %
- % Written by: Natasa Kovacevic
- % Modified in areas marked with ** (Nov, 2013: M. Cheung)
- % Last modified: Jan. 15, 2014
- % Copyright (C) 2013-2014, Natasa Kovacevic
- %
- % This file is a part of the MEG & PLS Pipeline (MEGPLS). For more
- % details, see the documentation included with the software package.
- %
- % MEGPLS is free software: you can redistribute it and/or modify it under
- % the terms of the GNU General Public License version 2 as published by
- % the Free Software Foundation. This program is distributed in the hope
- % that it will be useful, but WITHOUT ANY WARRANTY; without even the
- % implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- % See the GNU General Public License for more details.
- %
- % You should have received a copy of the GNU General Public License along
- % with this program. If not, you can download the license here:
- % <http://www.gnu.org/licenses/old-licenses/gpl-2.0>.
- % NK: note use set/get for fields that come prediscribed with objects (e.g. sliders)
- % and for fields that I added to handles. Use setappdata/getappdata for gui
- % Begin initialization code - DO NOT EDIT
- gui_Singleton = 0;
- gui_State = struct('gui_Name', mfilename, ...
- 'gui_Singleton', gui_Singleton, ...
- 'gui_OpeningFcn', @View4D_BRIK_OpeningFcn, ...
- 'gui_OutputFcn', @View4D_BRIK_OutputFcn, ...
- 'gui_LayoutFcn', [] , ...
- 'gui_Callback', []);
- if nargin && ischar(varargin{1})
- gui_State.gui_Callback = str2func(varargin{1});
- end
- if nargout
- [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
- else
- gui_mainfcn(gui_State, varargin{:});
- end
- % End initialization code - DO NOT EDIT
- %--- Executes just before View4D_BRIK is made visible. ---%
- %---------------------------------------------------------%
- function View4D_BRIK_OpeningFcn(hObject, eventdata, handles, varargin)
- % This function has no output args, see OutputFcn.
- % hObject handle to figure
- % eventdata reserved - to be defined in a future version of MATLAB
- % handles structure with handles and user data (see GUIDATA)
- % varargin command line arguments to View4D_BRIK (see VARARGIN)
- % Choose default command line output for View4D_BRIK
- handles.output = hObject;
- % Update handles structure
- guidata(hObject, handles);
- % Check inputs:
- if numel(varargin) < 4 | numel(varargin)>4
- disp('You must supply: anatomical underlay and functional 4D .BRIK file');
- disp('All files should be in AFNI format');
- disp('Usage: View4D_BSR(anat_img, brik_img, cellarray_of_otherdata, customlegendnames)');
- disp('Example: View4D_BSR(''anat+tlrc.BRIK'', ''functional+tlrc.BRIK'', [], [])');
- error('wrong number of inputs ');
- end
- % load anatomical BRIK file
- Opt.format = 'vector';
- [err,anat,Info,ErrMessage]=BrikLoad(varargin{1},Opt);
- handles.anat = anat;
- % load functional 4D .BRIK image:
- Opt.format = 'vector';
- [err,img,Info,ErrMessage]=BrikLoad(varargin{2},Opt);
- BSR.img = img;
- handles.dims = size(BSR.img); % 4-dimensional (x, y, z, time)
- if numel(size(BSR.img))==3, handles.dims(4) = 1; end
- handles.BSR = BSR;
- handles.Info = Info;
- handles.MainFuncFile = varargin{2};
- guidata(hObject, handles);
- %** Add ability to overlay multiple datasets in voxel timeseries axes.
- % load other .BRIK data to include in voxel timeseries:
- if ~isempty(varargin{3})
- for l=1:length(varargin{3})
- Opt.format = 'vector';
- [err,OtherImgData{l},Info,ErrMessage]=BrikLoad(varargin{3}{l},Opt);
-
- % Check dims of other image data.
- if size(OtherImgData{l}) ~= size(BSR.img)
- error('Optional datasets must be same dimension as the main functional image.');
- end
- end
- handles.OtherImgData = OtherImgData;
- handles.OtherImgName = varargin{3};
- else
- handles.OtherImgData = [];
- handles.OtherImgName = [];
- end
- %** Add ability to specify own legend in voxel-timeseries plot:
- if ~isempty(varargin{4})
- handles.CustomLegend = varargin{4};
- if length(handles.CustomLegend) ~= length(handles.OtherImgData) + 1
- disp('Error: Custom legend does not contain correct number of inputs.');
- disp(' - Legend names should include both the main functional image and optional datasets.');
- error('Custom Legend has wrong number of inputs.');
- end
- else
- handles.CustomLegend = [];
- end
-
- % Sets title to PLS LV info:
- %tmp=strfind(Info.HISTORY_NOTE, '***');
- % if ~isempty(tmp)
- % tmp=Info.HISTORY_NOTE(tmp:end);
- % loc=strfind(tmp,'\n');
- % finaltmp=tmp(1:(loc(1)-1));
- % set(handles.Title,'String',finaltmp);
- % else
- %** Changed to just display full filepath as title
- set(handles.Title,'String',varargin{2});
- %end
- % set view and sliders
- x = ceil(handles.dims(1)/2);
- y = ceil(handles.dims(2)/2);
- z = ceil(handles.dims(3)/2);
- set(handles.AxialSlider,'Min',1,'Max',handles.dims(3),'SliderStep',[1/(handles.dims(3)-1) 1/(handles.dims(3)-1)],'Value',z);
- set(handles.SagitalSlider,'Min',1,'Max',handles.dims(1),'SliderStep',[1/(handles.dims(1)-1) 1/(handles.dims(1)-1)],'Value',x);
- set(handles.CoronalSlider,'Min',1,'Max',handles.dims(2),'SliderStep',[1/(handles.dims(2)-1) 1/(handles.dims(2)-1)],'Value',y);
- setappdata(handles.Axialview,'slicenum',z);
- setappdata(handles.Sagitalview,'slicenum',x);
- setappdata(handles.Coronalview,'slicenum',y);
- if numel(size(BSR.img))==3
- handles.dims(4) = 1;
- set(handles.TimeptSlider,'Min',1,'Max',1.001,'SliderStep',[1 1],'Value',1);
- else
- set(handles.TimeptSlider,'Min',1,'Max',handles.dims(4),'SliderStep',[1/(handles.dims(4)-1) 1/(handles.dims(4)-1)],'Value',1);
- end
- % set up montage selection listbox and monatge viewing parameters
- set(handles.SelectMontage,'String',{'None','Axial','Sagittal','Coronal'});
- set(handles.MontageViewingTable,'data',[1 1 handles.dims(1); 1 1 handles.dims(2); 1 1 handles.dims(3); 1 1 3;]);
- % start with first timept
- set(handles.Timept,'String','1');
- % set up bsr, tbsr, blend
- UpdateBlend(handles);
- % start using gui
- UpdateSlices(x,y,z,handles);
- UpdateTimept(1,handles);
- guidata(hObject, handles); % Update handles structure
- function varargout = View4D_BRIK_OutputFcn(hObject, eventdata, handles)
- varargout{1} = handles.output;
- function UpdateBlend(handles)
- % set up bsr, tbsr, blend
- % this function is normally called only in the begining and when user
- % changes bsr thresholds -> because thhreshold is the only thing that
- % alters the blend and the colormap
- % clamp bsr image for better viewing
- %** get clamp range from textbox:
- %bsr_clamp = 5;
- bsr_clamp = str2num(get(handles.TextboxClampRange, 'String'));
- bsr = handles.BSR.img;
- bsr(find(bsr>=bsr_clamp)) = bsr_clamp; bsr(find(bsr<=-bsr_clamp)) = -bsr_clamp;
- % get bsr threshold
- %** Added check to prevent threshold from exceeding max/min of data or clamp
- posthresh = str2num(get(handles.BSR_posthresh,'String'));
- negthresh = str2num(get(handles.BSR_negthresh,'String'));
- maxvalue = getappdata(handles.BSR_posthresh,'d');
- minvalue = getappdata(handles.BSR_posthresh,'c');
- if posthresh > maxvalue | posthresh <= minvalue
- posthresh = maxvalue;
- set(handles.BSR_posthresh,'String', posthresh);
- end
- if negthresh < minvalue | negthresh >= maxvalue
- negthresh = minvalue;
- set(handles.BSR_negthresh,'String', negthresh);
- end
- % zero out bsr voxels below threshold
- tbsr = bsr;
- tbsr(find(tbsr<posthresh & tbsr>negthresh)) = 0;
- orig_tbsr = tbsr;
- % now map tbsr for colormap
- d = max(max(max(max(bsr)))); c = min(min(min(min(bsr))));
- if c==d, % that would happen only if tbsr is zero everywhere
- tbsr = ones(size(tbsr));
- else
- tbsr = round(255*(tbsr-c)/(d-c)+1);
- end
- [cmap, ignore_pts] = set_colormap(d,c,posthresh, negthresh);
- colormap(cmap);
- % map grayscale image into midwindow in the colormap
- img = handles.anat;
- a = min(min(min(img)));
- b = max(max(max(img)));
- img = round(ignore_pts(1) + (ignore_pts(end)-ignore_pts(1))*(img-a)/(b-a));
- img = min(max(img,ignore_pts(1)),ignore_pts(end));
- img = repmat(img,[1 1 1 handles.dims(4)]);
- blend = zeros([size(tbsr) 3]);
- for dim=1:3
- utmp = reshape(cmap(img,dim),size(tbsr));
- otmp = reshape(cmap(tbsr,dim),size(tbsr));
- blend(:,:,:,:,dim)= (orig_tbsr==0).* utmp + (orig_tbsr~=0).* otmp;
- end
- % attach blend and colormap related infor to be used in other gui
- % components
- setappdata(handles.BSR_posthresh,'blend',blend);
- setappdata(handles.BSR_posthresh,'cmap',cmap);
- setappdata(handles.BSR_posthresh,'ignore_pts', ignore_pts);
- setappdata(handles.BSR_posthresh,'c',c);
- setappdata(handles.BSR_posthresh,'d',d);
- function UpdateSlices(x,y,z,handles)
- % get current bsr thresholds
- posthresh = str2num(get(handles.BSR_posthresh,'String'));
- negthresh = str2num(get(handles.BSR_negthresh,'String'));
- bsr = handles.BSR.img;
- % get current time point and make sure that it makes sense
- tpt = round(get(handles.TimeptSlider,'value'));
- % get blend and colormap
- blend_allt= getappdata(handles.BSR_posthresh,'blend');
- blend = squeeze(blend_allt(:,:,:,tpt,:));
- cmap = getappdata(handles.BSR_posthresh,'cmap');
- colormap(cmap);
- % AFNI IJK coordinates:
- set(handles.Coord,'String',[num2str(x) ' ' num2str(y) ' ' num2str(z)]);
- % AFNI indexing convention for AFNI viewer & functions starts at 0.
- % Note: AFNI reads orientation in voxel-storage order, so LPI in AFNI is RAS (in spatial direction)
- % Recall: RAS is orientation of coordinate systems of TLRC and MNI templates.
- [err, XYZdic] = AFNI_Index2XYZcontinuous([x-1, y-1, z-1], handles.Info, 'LPI');
- set(handles.MNI_coord, 'String', [num2str(XYZdic(1)) ' ' num2str(XYZdic(2)) ' ' num2str(XYZdic(3))]);
- % udate slider positions
- set(handles.AxialSlider,'Value',z);
- set(handles.SagitalSlider,'Value',x);
- set(handles.CoronalSlider,'Value',y);
- setappdata(handles.Axialview,'slicenum',z);
- setappdata(handles.Sagitalview,'slicenum',x);
- setappdata(handles.Coronalview,'slicenum',y);
- % update slice views
- col = [0 0.8 0];
- axes(handles.Axialview); % make this current axes
- tmp=permute(squeeze(blend(:,:,z,:)),[2 1 3]);
- image(tmp,'ButtonDownFcn',{@click_axial,handles});
- set(handles.Axialview,'ydir','normal','xtick',[],'ytick',[]);
- line([x x],[1 handles.dims(2)],'color',[0 1 0],'visible','on');
- line([1 handles.dims(1)],[y y],'color',[0 1 0],'visible','on');
- text(2,2,['z=' num2str(z)],'fontsize',12,'fontweight','bold','color',[0 1 0.3]);
- axes(handles.Sagitalview); % make this current axes
- image(permute(squeeze(blend(x,:,:,:)),[2 1 3]),'ButtonDownFcn',{@click_sagital,handles});
- set(handles.Sagitalview,'ydir','normal','xtick',[],'ytick',[]);
- line([y y],[1 handles.dims(3)],'color',[0 1 0],'visible','on');
- line([1 handles.dims(2)],[z z],'color',[0 1 0],'visible','on');
- text(2,2,['x=' num2str(x)],'color','g','fontsize',12,'fontweight','bold');
- text(0,handles.dims(3)+2,num2str(bsr(x,y,z,tpt)),'fontsize',12,'fontweight','bold','color','c');
- axes(handles.Coronalview); % make this current axes
- image(permute(squeeze(blend(:,y,:,:)),[2 1 3]),'ButtonDownFcn',{@click_coronal,handles});
- set(handles.Coronalview,'ydir','normal','xtick',[],'ytick',[]);
- line([x x],[1 handles.dims(3)],'color',[0 1 0],'visible','on');
- line([1 handles.dims(1)],[z z],'color',[0 1 0],'visible','on');
- text(2,2,['y=' num2str(y)],'color','g','fontsize',12,'fontweight','bold');
- text(0,handles.dims(3)+2,num2str(bsr(x,y,z,tpt)),'fontsize',12,'fontweight','bold','color','m');
- % update BSR colorbar
- axes(handles.colorbar_view);
- imagesc([1:256]'); colormap(cmap);
- ignore_pts = getappdata(handles.BSR_posthresh,'ignore_pts');
- %**Commented out: Modified below to be more robust accomodating different datasets
- %set(gca, 'ydir', 'normal', 'ytick',[1 ignore_pts(1) ignore_pts(end) 256], 'YTickLabel', {num2str(getappdata(handles.BSR_posthresh,'c')), num2str(negthresh), num2str(posthresh), num2str(getappdata(handles.BSR_posthresh,'d'))}, 'XTickLabel', []);
- if ignore_pts(1) <= 1
- set(gca, 'ydir', 'normal', 'ytick',[1 ignore_pts(end) 256], 'YTickLabel', {num2str(getappdata(handles.BSR_posthresh,'c')), num2str(posthresh), num2str(getappdata(handles.BSR_posthresh,'d'))}, 'XTickLabel', []);
- elseif ignore_pts(end) >= 256
- set(gca, 'ydir', 'normal', 'ytick',[1 ignore_pts(1) 256], 'YTickLabel', {num2str(getappdata(handles.BSR_posthresh,'c')), num2str(negthresh), num2str(getappdata(handles.BSR_posthresh,'d'))}, 'XTickLabel', []);
- elseif ignore_pts(1) <= 1 && ignore_pts(end) >= 256
- set(gca, 'ydir', 'normal', 'ytick',[1 256], 'YTickLabel', {num2str(getappdata(handles.BSR_posthresh,'c')), num2str(getappdata(handles.BSR_posthresh,'d'))}, 'XTickLabel', []);
- else
- set(gca, 'ydir', 'normal', 'ytick',[1 ignore_pts(1) ignore_pts(end) 256], 'YTickLabel', {num2str(getappdata(handles.BSR_posthresh,'c')), num2str(negthresh), num2str(posthresh), num2str(getappdata(handles.BSR_posthresh,'d'))}, 'XTickLabel', []);
- end
- % update BSR time series plot
- axes(handles.BSR_timeseries);
- Tseries = squeeze(handles.BSR.img(x,y,z,:));
- if numel(Tseries) > 1
- at = min(Tseries); bt = max(Tseries);
- num_tpts = numel(Tseries);
- tpts = [1:num_tpts];
- plot(tpts,Tseries, 'LineStyle', '-', 'LineWidth', 2);
- hold on;
- if bt > at
- e = (bt-at)/20;
- set(gca,'ylim',[at-e bt+e],'xlim',[0 numel(Tseries)+1]);
- else
- set(gca,'ylim',[-1 1],'xlim',[0 numel(Tseries)+1]);
- end
- hold all;
- end
- %** Add ability to overlay multiple datasets in voxel timeseries axes.
- % overlay other specified datasets onto timeseries plot
- if ~isempty(handles.OtherImgData)
- num_OtherData = length(handles.OtherImgData);
- tmparray = zeros(num_OtherData, length(Tseries));
- for l=1:num_OtherData
- tmparray(l,:) = squeeze(handles.OtherImgData{l}(x,y,z,:));
- end
- tmparray = tmparray';
- plot(tmparray, 'LineStyle', '-', 'LineWidth', 1);
- hold on;
-
- %** add ability for custom legendname
- if ~isempty(handles.CustomLegend)
- clickableLegend(handles.CustomLegend, 'interpreter', 'none');
- else
- [~, FuncFile, ~] = fileparts(handles.MainFuncFile);
- LegendData{1} = FuncFile;
- for f = 1:num_OtherData
- [~, OtherFile, ~] = fileparts(handles.OtherImgName{f});
- LegendData{f+1} = OtherFile;
- end
- clickableLegend(LegendData, 'interpreter', 'none');
- end
- end
- % horizontal dotted red lines indicate bsr thresholds
- h=line([1 num_tpts], [posthresh posthresh]);
- set(h, 'LineStyle', '--', 'Color', 'r');
- h=line([1 num_tpts], [negthresh negthresh]);
- set(h, 'LineStyle', '--', 'Color', 'r');
- hold off;
- title(['Value = ',num2str(Tseries(tpt))],'color','r','fontsize',14);
- minval = min(min(Tseries),negthresh); maxval = max(max(Tseries),posthresh);
- E = (maxval - minval)/10;
- set(gca,'ylim',[minval-E maxval+E]);
- % vertical gray line indicates current tpt
- h = line([tpt tpt], [minval-E maxval+E]);
- set(h, 'LineStyle', '-', 'Color', [0.6 0.6 0.6]);
- set(gca,'ButtonDownFcn',{@click_BSR_ts,handles},'xlim',[0 num_tpts+1]);
- setappdata(handles.PrintBSRButton,'bsr_ts',Tseries);
- function UpdateTimept(tpt,handles)
- % update views
- x = getappdata(handles.Sagitalview,'slicenum');
- y = getappdata(handles.Coronalview,'slicenum');
- z = getappdata(handles.Axialview,'slicenum');
- UpdateSlices(x,y,z,handles);
- function AxialSlider_Callback(hObject, eventdata, handles)
- z = round(get(hObject, 'Value'));
- x = round(get(handles.SagitalSlider,'Value'));
- y = round(get(handles.CoronalSlider,'Value'));
- UpdateSlices(x,y,z,handles);
- function SagitalSlider_Callback(hObject, eventdata, handles)
- x = round(get(hObject, 'Value'));
- z = round(get(handles.AxialSlider,'Value'));
- y = round(get(handles.CoronalSlider,'Value'));
- UpdateSlices(x,y,z,handles);
- function CoronalSlider_Callback(hObject, eventdata, handles)
- y = round(get(hObject, 'Value'));
- z = round(get(handles.AxialSlider,'Value'));
- x = round(get(handles.SagitalSlider,'Value'));
- UpdateSlices(x,y,z,handles);
- function Timept_Callback(hObject, eventdata, handles)
- tpt = round(str2num(get(hObject,'String')));
- if tpt<1 || tpt>handles.dims(4)
- prompt={
- ['Invalid Time.'];
- ['Time must be # between: 1 & ',num2str(handles.dims(4))]};
- warndlg(prompt,'Warning:','modal');
- end
- set(handles.TimeptSlider,'Value',tpt);
- UpdateTimept(tpt,handles);
- function TimeptSlider_Callback(hObject, eventdata, handles)
- tpt = round(get(hObject, 'Value'));
- set(handles.Timept,'String',num2str(tpt));
- UpdateTimept(tpt,handles);
- function click_axial(src,eventdata,handles)%callback for buttonclick
- c= ginput(1);
- x = round(c(1,1));
- y = round(c(1,2));
- z = getappdata(handles.Axialview,'slicenum');
- UpdateSlices(x,y,z,handles);
- function click_sagital(src,eventdata,handles)
- %c = get(gca,'CurrentPoint');
- c= ginput(1);
- y = round(c(1,1));
- z = round(c(1,2));
- x = getappdata(handles.Sagitalview,'slicenum');
- UpdateSlices(x,y,z,handles);
- function click_coronal(src,eventdata,handles)
- %c = get(gca,'CurrentPoint');
- c= ginput(1);
- x = round(c(1,1));
- z = round(c(1,2));
- y = getappdata(handles.Coronalview,'slicenum');
- UpdateSlices(x,y,z,handles);
- function click_BSR_ts(src,eventdata,handles)
- c = ginput(1);
- tpt = round(c(1));
- tpt = min(max(1,tpt), handles.dims(4));
- set(handles.Timept,'String',num2str(tpt));
- set(handles.TimeptSlider,'value',tpt);
- UpdateTimept(tpt,handles);
- function click_GPAVG_ts(src,eventdata,handles)
- c = ginput(1);
- tpt = round(c(1));
- tpt = min(max(1,tpt), handles.dims(4));
- set(handles.Timept,'String',tpt);
- set(handles.TimeptSlider,'value',tpt);
- UpdateTimept(tpt,handles);
- function Coord_Callback(hObject, eventdata, handles) % user eneters voxel coordinates
- coord = round(str2num(get(hObject,'String')));
- if (coord(1)<1 || coord(1)>handles.dims(1)) || (coord(2)<1 || coord(2)>handles.dims(2)) || (coord(3)<1 || coord(2)>handles.dims(3))
- prompt={
- ['Invalid Coordinate.'];
- ['X-coord must be # between: 1 & ',num2str(handles.dims(1))];
- ['Y-coord must be # between: 1 & ',num2str(handles.dims(2))];
- ['Z-coord must be # between: 1 & ',num2str(handles.dims(3))]};
- warndlg(prompt,'Warning:','modal');
- end
- UpdateSlices(coord(1),coord(2),coord(3),handles);
- function MNI_coord_Callback(hObject, eventdata, handles)
- mni_coord = round(str2num(get(hObject,'String')));
- [err, coord] = AFNI_XYZcontinuous2Index(mni_coord, handles.Info, 'LPI', 3);
- coord = coord+1; % AFNI indexing convention starts at 0.
- UpdateSlices(coord(1),coord(2),coord(3),handles);
- function BSR_negthresh_Callback(hObject, eventdata, handles)
- thresh = str2num(get(handles.BSR_negthresh,'String'));
- if thresh>0, set(handles.BSR_negthresh,'String','0'); end
- UpdateBlend(handles);
- z = getappdata(handles.Axialview,'slicenum');
- x = getappdata(handles.Sagitalview,'slicenum');
- y = getappdata(handles.Coronalview,'slicenum');
- UpdateSlices(x,y,z,handles);
- function BSR_posthresh_Callback(hObject, eventdata, handles)
- thresh = str2num(get(handles.BSR_posthresh,'String'));
- if thresh<0, set(handles.BSR_posthresh,'String','0'); end
- UpdateBlend(handles);
- z = getappdata(handles.Axialview,'slicenum');
- x = getappdata(handles.Sagitalview,'slicenum');
- y = getappdata(handles.Coronalview,'slicenum');
- UpdateSlices(x,y,z,handles);
- %** Added textbox for clamp range
- function TextboxClampRange_Callback(hObject, eventdata, handles)
- clamp = str2num(get(handles.TextboxClampRange, 'String'));
- if clamp<=0, set(handles.TextboxClampRange, 'String', '10'); end
- UpdateBlend(handles);
- z = getappdata(handles.Axialview,'slicenum');
- x = getappdata(handles.Sagitalview,'slicenum');
- y = getappdata(handles.Coronalview,'slicenum');
- UpdateSlices(x,y,z,handles);
- function SelectMontage_Callback(hObject, eventdata, handles)
- contents = cellstr(get(hObject,'String')); % get the whole list as a cell array of strings
- montage_type = contents{get(hObject,'Value')}; % get current selection
- if strmatch(montage_type,{'Axial','Sagittal','Coronal'})
- TableData = get(handles.MontageViewingTable,'Data'); % get User defined parmaeters for the montage
- figure('NumberTitle','off','name',['Montage ' montage_type]);
- dims = handles.dims;
- % get blend and subsample according to the montage table parameters
- blend = getappdata(handles.BSR_posthresh,'blend');
- subblend = blend(TableData(1,1):TableData(1,2):TableData(1,3),TableData(2,1):TableData(2,2):TableData(2,3),TableData(3,1):TableData(3,2):TableData(3,3),TableData(4,1):TableData(4,2):TableData(4,3),:); % (x y z t rgb)
-
- % determine axes permuation order
- switch montage_type
- case 'Axial', ord = [1 2 3 4]; xlab = 'z slice';
- case 'Sagittal', ord = [2 3 1 4]; xlab = 'x slice';
- case 'Coronal', ord = [1 3 2 4]; xlab = 'y slice';
- end
-
- % permute subblend in awy that is good for the display
- subblend = permute(subblend,[ord(2) ord(4) ord(1) ord(3) 5]); % 5th dim is rgb
- for d=1:4
- span{d} = TableData(ord(d),1):TableData(ord(d),2):TableData(ord(d),3);
- end
-
- % determine vertical image size (dim1) and horizontal image size (dim2)
- dim1 = numel(span{2}) * numel(span{4}); % rows = ysize*time
- dim2 = numel(span{1}) * numel(span{3}); % columns = xsize*zsize
-
- % reshape subblend and show
- subblend = reshape(subblend,dim1,dim2,3);
- image(subblend,'ButtonDownFcn',{@click_Montage,handles});
- set(gca,'ydir','normal','xtick',([1:numel(span{3})]-0.5)*numel(span{1}),'xticklabel',cellstr(int2str(span{3}'))','ytick',([1:numel(span{4})]-0.5)*numel(span{2}),'yticklabel',cellstr(int2str(span{4}'))');
- ylabel('Time');
- xlabel(xlab);
-
- % get current gui (x y z t) coordinate
- z = getappdata(handles.Axialview,'slicenum');
- x = getappdata(handles.Sagitalview,'slicenum');
- y = getappdata(handles.Coronalview,'slicenum');
- t = round(get(handles.TimeptSlider,'value'));
- coord = [x y z t];
-
- % tranaslate this coordinate into this image space
- for d=1:4, subcoord(d) = round((coord(d)-TableData(d,1))/TableData(d,2))+1; end
- subcoord = subcoord(ord);
-
- % plot crosshair and
- horpos = numel(span{2})*(subcoord(4)-1) + subcoord(2);
- verpos = numel(span{1})*(subcoord(3)-1) + subcoord(1);
- horline = line([1 dim2],[horpos horpos],'color',[0 1 0],'visible','on');
- verline = line([verpos verpos],[1 dim1],'color',[0 1 0],'visible','on');
-
- % record current montage window settings
- setappdata(handles.MontageViewingTable,'span',span);
- setappdata(handles.MontageViewingTable,'ord',ord);
- setappdata(handles.MontageViewingTable,'subcoord',subcoord);
- setappdata(handles.MontageViewingTable,'fig',gcf);
- setappdata(handles.MontageViewingTable,'horline',horline);
- setappdata(handles.MontageViewingTable,'verline',verline);
- setappdata(handles.MontageViewingTable,'horpos',horpos);
- setappdata(handles.MontageViewingTable,'verpos',verpos);
- end
- function click_Montage(src,eventdata,handles)%callback for buttonclick
- % % when user click on the montage figure reverse the caluclation from SelectMontage_Callbac
- % % to obtain [x y z t] in the original image space
- % c = ginput(1);
- % horpos = round(c(1,1));
- % verpos = round(c(1,2));
- % rspan = getappdata(handles.MontageViewingTable,'span');
- % ord = getappdata(handles.MontageViewingTable,'ord');
- % TableData = get(handles.MontageViewingTable,'Data'); % get User defined parmaeters for the montage
- % revord(ord) = [1:4]; % reverse order; this statement defines new variable revord
- % for d=1:4, span{d} = rspan{revord(d)}; end
- % subcoord(2) = mod(horpos,numel(span{2}));
- % subcoord(4) = (horpos - subcoord(2))/numel(span{2})+1;
- % subcoord(1) = mod(verpos,numel(span{1}));
- % subcoord(3) = (verpos - subcoord(1))/numel(span{1})+1;
- % revord(ord) = [1:4]; % reverse order; this statement defines new variable revord
- % subcoord
- % ord
- % revord
- % %subcoord = subcoord(revord)
- % for d=1:4,
- % coord(d) = round( (subcoord(d)-1)*TableData(d,2) + TableData(d,1) );
- % coord(d) = min(max(1,coord(d)),handles.dims(d));
- % end
- % set(handles.Timept,'String',num2str(coord(4)));
- % set(handles.TimeptSlider,'value',coord(4));
- %
- % % redraw crosshairs
- % dim1 = numel(span{2}) * numel(span{4}); % rows = ysize*time
- % dim2 = numel(span{1}) * numel(span{3}); % columns = xsize*zsize
- % horline = getappdata(handles.MontageViewingTable,'horline');
- % verline = getappdata(handles.MontageViewingTable,'verline');
- % set(horline,'visible','off');set(verline,'visible','off');
- % figure(getappdata(handles.MontageViewingTable,'fig'));
- % horline = line([1 dim2],[horpos horpos],'color',[0 1 0],'visible','on');
- % verline = line([verpos verpos],[1 dim1],'color',[0 1 0],'visible','on');
- % setappdata(handles.MontageViewingTable,'horline',horline);
- % setappdata(handles.MontageViewingTable,'verline',verline);
- % setappdata(handles.Sagitalview,'slicenum',coord(1));
- % setappdata(handles.Coronalview,'slicenum',coord(2));
- % setappdata(handles.Axialview,'slicenum',coord(3));
- % set(handles.Timept,'String',num2str(coord(4)));
- % set(handles.TimeptSlider,'value',coord(4));
- % UpdateTimept(coord(4),handles);
- function PrintBSRButton_Callback(hObject, eventdata, handles)
- val = get(hObject,'Value');
- if val==1
- MainVoxTS = getappdata(handles.PrintBSRButton,'bsr_ts')
- set(hObject,'Value',0);
- end
- %** Also print out timeseries of other datasets.
- if ~isempty(handles.OtherImgData)
- x = getappdata(handles.Sagitalview,'slicenum');
- y = getappdata(handles.Coronalview,'slicenum');
- z = getappdata(handles.Axialview,'slicenum');
- Tseries = squeeze(handles.BSR.img(x,y,z,:));
- num_OtherData = length(handles.OtherImgData);
- tmparray = zeros(num_OtherData, length(Tseries));
- for l=1:num_OtherData
- tmparray(l,:) = squeeze(handles.OtherImgData{l}(x,y,z,:));
- end
- tmparray = tmparray';
-
- OtherVoxTS = tmparray
- end
- function MontageViewingTable_CellEditCallback(hObject, eventdata, handles)
- val = round(str2num(eventdata.EditData)); % get cell content as entered by user
- inds = eventdata.Indices; % find (i,j) position in the table
- % if new value is outside of alowable dims, then change back to previous
- % cell content
- if ~(val >=1 & val <= handles.dims(inds(1)))
- TableData = get(handles.MontageViewingTable,'Data');
- TableData(inds(1),inds(2)) = eventdata.PreviousData;
- set(handles.MontageViewingTable,'Data',TableData);
- end
- function MontageViewingTable_CellSelectionCallback(hObject, eventdata, handles)
- % hObject handle to MontageViewingTable (see GCBO)
- % eventdata structure with the following fields (see UITABLE)
- % Indices: row and column indices of the cell(s) currently selecteds
- % handles structure with handles and user data (see GUIDATA)
- % NK: note we must have this function even if it doesn't do anything!!!!!
- function [cmap,ignore_pts] = set_colormap(max_bsr, min_bsr, pos_bsr_thresh, neg_bsr_thresh)
- % written by Jimmy - NK made some changes
- % set the display colormap based on the max/min display values and
- % the threshold setting.
- %
- % The upper colors are coming from the entries of [140:239] of the
- % 255 jet colormap, and the lower colors are from the entries of
- % [1:100] of the colormap.
- %
- range_interval = max_bsr - min_bsr;
- upper_interval = max_bsr - pos_bsr_thresh;
- lower_interval = neg_bsr_thresh - min_bsr; % abs(min_bsr) - abs(neg_bsr_thresh);
-
- % colormap entries for the upper range values, using the
- % entries of [140:239] from the 255 jet colormap
- %
- num_upper_colors = 0;
- if (upper_interval > 0)
- num_upper_colors = round(upper_interval / range_interval * 255);
- cmap_size = round(255 * num_upper_colors/100);
- first_color_idx = round(140 / 255 * cmap_size);
- last_color_idx = first_color_idx + num_upper_colors - 1;
- uppermap = jet(cmap_size);
- upper_colors = uppermap(first_color_idx:last_color_idx,:);
- end;
-
- % colormap entries for the lower range values, using the
- % entries of [1:100] from the 255 jet colormap
- %
- num_lower_colors = 0;
- if (lower_interval > 0)
- num_lower_colors = round(lower_interval / range_interval * 255);
- cmap_size = round(255 * num_lower_colors/100);
- first_color_idx = 1;
- last_color_idx = num_lower_colors;
- lowermap = jet(cmap_size);
- lower_colors = lowermap(first_color_idx:last_color_idx,:);
- end;
-
- cmap = zeros(256,3);
- cmap(1:255,:) = jet(255);
-
- ignore_pts = [(num_lower_colors+1):(255-num_upper_colors)];
-
- if (num_lower_colors > 0),
- cmap(1:num_lower_colors,:) = lower_colors;
- end;
- if (num_upper_colors > 0),
- if ~isempty(ignore_pts)
- cmap((ignore_pts(end)+1):255,:) = upper_colors;
- else
- cmap((255-num_upper_colors+1):255,:) = upper_colors;
- end
- end
- if ~isempty(ignore_pts)
- %cmap(ignore_pts,:) = ones(length(ignore_pts),3) * 140/255;
- cmap(ignore_pts,:) = gray(numel(ignore_pts));
- end
- cmap(256,:) = [1 1 1];
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %%%%%%%%% Create functions
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- function BSR_posthresh_CreateFcn(hObject, eventdata, handles)
- if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
- set(hObject,'BackgroundColor','white');
- end
- function BSR_negthresh_CreateFcn(hObject, eventdata, handles)
- if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
- set(hObject,'BackgroundColor','white');
- end
- function MNI_coord_CreateFcn(hObject, eventdata, handles)
- if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
- set(hObject,'BackgroundColor','white');
- end
- function Coord_CreateFcn(hObject, eventdata, handles)
- if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
- set(hObject,'BackgroundColor','white');
- end
- function TimeptSlider_CreateFcn(hObject, eventdata, handles)
- if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
- set(hObject,'BackgroundColor',[.9 .9 .9]);
- end
- function Timept_CreateFcn(hObject, eventdata, handles)
- if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
- set(hObject,'BackgroundColor','white');
- end
- function CoronalSlider_CreateFcn(hObject, eventdata, handles)
- if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
- set(hObject,'BackgroundColor',[.9 .9 .9]);
- end
- function SagitalSlider_CreateFcn(hObject, eventdata, handles)
- if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
- set(hObject,'BackgroundColor',[.9 .9 .9]);
- end
- function AxialSlider_CreateFcn(hObject, eventdata, handles)
- if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
- set(hObject,'BackgroundColor',[.9 .9 .9]);
- end
- function SelectMontage_CreateFcn(hObject, eventdata, handles)
- if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
- set(hObject,'BackgroundColor','white');
- end
- %** Added clamp range textbox
- % --- Executes during object creation, after setting all properties.
- function TextboxClampRange_CreateFcn(hObject, eventdata, handles)
- if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
- set(hObject,'BackgroundColor','white');
- end
|